<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-169911533-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-169911533-1');
</script>

  

  
  <title>JVM 05 运行时数据区之方法区 (MethodArea) | 空城盼故人</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="google-site-verification" content="NOVpqBhVVjZHOamocUf3Grijt7xAK_Engoe_FNrxE3Q" />
  <meta name="baidu-site-verification" content="HBrapLOndy" />
  
  <meta name="keywords" content="许嵩老公" />
  
  <meta name="description" content="方法区概述  1 栈和堆和方法区间的交互关系 2 方法区的理解 方法区在哪里 HotSpot中方法区的演进   3 设置方法区大小与OOM 4 方法区的内部结构 方法区 (Method Area) 存储什么 类型信息 域 (Field) 信息 方法 (Method) 信息 字节码角度举例查看   non-final 的类变量 补充说明：全局常量：final static class 文件中常量池的">
<meta property="og:type" content="article">
<meta property="og:title" content="JVM 05 运行时数据区之方法区 (MethodArea)">
<meta property="og:url" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/index.html">
<meta property="og:site_name" content="空城盼故人">
<meta property="og:description" content="方法区概述  1 栈和堆和方法区间的交互关系 2 方法区的理解 方法区在哪里 HotSpot中方法区的演进   3 设置方法区大小与OOM 4 方法区的内部结构 方法区 (Method Area) 存储什么 类型信息 域 (Field) 信息 方法 (Method) 信息 字节码角度举例查看   non-final 的类变量 补充说明：全局常量：final static class 文件中常量池的">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA%E7%BB%93%E6%9E%84%E5%9B%BE.png">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/%E5%86%85%E5%AD%98%E5%8C%BA%E5%9F%9F.svg">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/%E6%A0%88%E5%A0%86%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E4%BA%A4%E4%BA%92%E5%85%B3%E7%B3%BB.png">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/LoadedClassesNumber.png">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/%E6%96%B9%E6%B3%95%E5%8C%BA1.svg">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/%E6%96%B9%E6%B3%95%E5%8C%BA2.svg">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/HotSpot%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%B8%AD%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E6%BC%94%E8%BF%9B%E7%BB%86%E8%8A%82.svg">
<meta property="article:published_time" content="2020-07-17T06:36:32.000Z">
<meta property="article:modified_time" content="2020-08-08T13:11:50.392Z">
<meta property="article:author" content="许嵩老公">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="JVM">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://xiaoyan94.github.io/2020/07/17/JVM-05/%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA%E7%BB%93%E6%9E%84%E5%9B%BE.png">
  
    <link rel="alternate" href="../../../../atom.xml" title="空城盼故人" type="application/atom+xml">
  
  
    <link rel="icon" href="https://q1.qlogo.cn/g?b=qq&nk=979727728&s=640">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="../../../../css/style.css">

  
<link rel="stylesheet" href="../../../../css/highlight.css">

<meta name="generator" content="Hexo 4.2.1"></head>

<body>
  <div id="fullpage" class="mobile-nav-right">
    <div class="fixed"></div>
    
      <div id="wrapper">
    
    
      <header id="header">
  <div id="nav-toggle" class="nav-toggle"></div>
  <div class="head-box global-width">
    <nav class="nav-box nav-right">
      
        <a class="nav-item" href="../../../../index.html" title
        
        >首页</a>
      
        <a class="nav-item" href="../../../../archives" title
        
        >归档</a>
      
        <a class="nav-item" href="../../../../quick-notes" title
        
        >小抄</a>
      
        <a class="nav-item" href="../../../../about" title
        
        >关于</a>
      
    </nav>
  </div>
</header>
      <div id="middlecontent" title class="global-width sidebar-right">
        <section id="main"><article id="post-JVM-05" class="article global-container article-type-post" itemscope itemprop="blogPost">
  
    <header class="article-header">
      
  
    <h1 class="article-title" itemprop="name">
      JVM 05 运行时数据区之方法区 (MethodArea)
    </h1>
  

    </header>
  
  <div class="article-meta">
    <a href="" class="article-date">
  <time datetime="2020-07-17T06:36:32.000Z" itemprop="datePublished">2020-07-17</time>
</a>
    
    
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="../../../../tags/JVM/" rel="tag">JVM</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="../../../../tags/Java/" rel="tag">Java</a></li></ul>

  </div>
  
    <span id="busuanzi_container_page_pv">
      本文总阅读量<span id="busuanzi_value_page_pv"></span>次
    </span>
  

  <div class="article-inner">
    
    <div class="article-content article-content-cloud" itemprop="articleBody">
      
        
        <p>方法区概述</p>
<ul>
<li><a href="#1-%E6%A0%88%E5%92%8C%E5%A0%86%E5%92%8C%E6%96%B9%E6%B3%95%E5%8C%BA%E9%97%B4%E7%9A%84%E4%BA%A4%E4%BA%92%E5%85%B3%E7%B3%BB">1 栈和堆和方法区间的交互关系</a></li>
<li><a href="#2-%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E7%90%86%E8%A7%A3">2 方法区的理解</a><ul>
<li><a href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E5%9C%A8%E5%93%AA%E9%87%8C">方法区在哪里</a></li>
<li><a href="#HotSpot%E4%B8%AD%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E6%BC%94%E8%BF%9B">HotSpot中方法区的演进</a></li>
</ul>
</li>
<li><a href="#3-%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%B3%95%E5%8C%BA%E5%A4%A7%E5%B0%8F%E4%B8%8EOOM">3 设置方法区大小与OOM</a></li>
<li><a href="#4-%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E5%86%85%E9%83%A8%E7%BB%93%E6%9E%84">4 方法区的内部结构</a><ul>
<li><a href="#%E6%96%B9%E6%B3%95%E5%8C%BA-Method-Area-%E5%AD%98%E5%82%A8%E4%BB%80%E4%B9%88">方法区 (Method Area) 存储什么</a><ul>
<li><a href="#%E7%B1%BB%E5%9E%8B%E4%BF%A1%E6%81%AF">类型信息</a></li>
<li><a href="#%E5%9F%9F-Field-%E4%BF%A1%E6%81%AF">域 (Field) 信息</a></li>
<li><a href="#%E6%96%B9%E6%B3%95-Method-%E4%BF%A1%E6%81%AF">方法 (Method) 信息</a></li>
<li><a href="#%E5%AD%97%E8%8A%82%E7%A0%81%E8%A7%92%E5%BA%A6%E4%B8%BE%E4%BE%8B%E6%9F%A5%E7%9C%8B">字节码角度举例查看</a></li>
</ul>
</li>
<li><a href="#non-final-%E7%9A%84%E7%B1%BB%E5%8F%98%E9%87%8F">non-final 的类变量</a></li>
<li><a href="#%E8%A1%A5%E5%85%85%E8%AF%B4%E6%98%8E%E5%85%A8%E5%B1%80%E5%B8%B8%E9%87%8Ffinal-static">补充说明：全局常量：<code>final static</code></a></li>
<li><a href="#class-%E6%96%87%E4%BB%B6%E4%B8%AD%E5%B8%B8%E9%87%8F%E6%B1%A0%E7%9A%84%E7%90%86%E8%A7%A3">class 文件中常量池的理解</a><ul>
<li><a href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0-VS-%E5%B8%B8%E9%87%8F%E6%B1%A0">运行时常量池 VS 常量池</a></li>
<li><a href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E5%B8%B8%E9%87%8F%E6%B1%A0">为什么需要常量池</a></li>
<li><a href="#%E5%B8%B8%E9%87%8F%E6%B1%A0%E4%B8%AD%E6%9C%89%E4%BB%80%E4%B9%88">常量池中有什么</a></li>
<li><a href="#%E5%B0%8F%E7%BB%93">小结</a></li>
</ul>
</li>
<li><a href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0%E7%9A%84%E7%90%86%E8%A7%A3">运行时常量池的理解</a><ul>
<li><a href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0">运行时常量池</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#5-%E6%96%B9%E6%B3%95%E5%8C%BA%E4%BD%BF%E7%94%A8%E4%B8%BE%E4%BE%8B">5 方法区使用举例</a></li>
<li><a href="#6-%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E6%BC%94%E8%BF%9B%E7%BB%86%E8%8A%82">6 方法区的演进细节</a><ul>
<li><a href="#%E6%B0%B8%E4%B9%85%E4%BB%A3%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E8%A2%AB%E5%85%83%E7%A9%BA%E9%97%B4%E6%9B%BF%E6%8D%A2">永久代为什么要被元空间替换</a></li>
<li><a href="#StringTable%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E8%B0%83%E6%95%B4%E4%BD%8D%E7%BD%AE">StringTable为什么要调整位置</a></li>
<li><a href="#%E5%A6%82%E4%BD%95%E8%AF%81%E6%98%8E%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E5%AD%98%E5%9C%A8%E5%93%AA">如何证明静态变量存在哪</a></li>
</ul>
</li>
<li><a href="#7-%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6">7 方法区的垃圾回收</a></li>
<li><a href="#8-%E6%80%BB%E7%BB%93">8 总结</a></li>
</ul>
<a id="more"></a>

<h2 id="1-栈和堆和方法区间的交互关系"><a href="#1-栈和堆和方法区间的交互关系" class="headerlink" title="1 栈和堆和方法区间的交互关系"></a>1 栈和堆和方法区间的交互关系</h2><p><img src="/2020/07/17/JVM-05/%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA%E7%BB%93%E6%9E%84%E5%9B%BE.png" alt="运行时数据区结构图"></p>
<p>从运行时数据区结构来看，方法区是要讨论的另一个结构。</p>
<p>从线程共享与否的角度来看</p>
<p><img src="/2020/07/17/JVM-05/%E5%86%85%E5%AD%98%E5%8C%BA%E5%9F%9F.svg" alt="内存区域"></p>
<p>栈、堆、方法区的交互关系</p>
<p><img src="/2020/07/17/JVM-05/%E6%A0%88%E5%A0%86%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E4%BA%A4%E4%BA%92%E5%85%B3%E7%B3%BB.png" alt="栈、堆、方法区的交互关系"></p>
<hr>
<h2 id="2-方法区的理解"><a href="#2-方法区的理解" class="headerlink" title="2 方法区的理解"></a>2 方法区的理解</h2><p><a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4" target="_blank" rel="noopener">摘自 Oracle 官网 JVM 规范 2.5.4. Method Area</a></p>
<p>The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the “text” segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (<a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9" target="_blank" rel="noopener">§2.9</a>) used in class and instance initialization and interface initialization.</p>
<p>The method area is created on virtual machine start-up. Although the method area is logically part of the heap, simple implementations may choose not to either garbage collect or compact it. This specification does not mandate the location of the method area or the policies used to manage compiled code. The method area may be of a fixed size or may be expanded as required by the computation and may be contracted if a larger method area becomes unnecessary. The memory for the method area does not need to be contiguous.</p>
<p><em>A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the method area, as well as, in the case of a varying-size method area, control over the maximum and minimum method area size.</em></p>
<p>The following exceptional condition is associated with the method area:</p>
<ul>
<li><strong>If memory in the method area cannot be made available to satisfy an allocation request, the Java Virtual Machine throws an OutOfMemoryError.</strong></li>
</ul>
<h3 id="方法区在哪里"><a href="#方法区在哪里" class="headerlink" title="方法区在哪里"></a>方法区在哪里</h3><p>《Java 虚拟机规范》中明确说明：“尽管所有的方法区在逻辑上是属于堆的一部分，但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。” 但对于 HotSpot JVM 而言，方法区还有一个别名叫做 Non-Heap（非堆），目的就是要和堆分开。</p>
<p>所以，<strong>方法区看作是一块独立于 Java 堆的内存空间</strong>。</p>
<ul>
<li>方法区 (Method Area) 与 Java 堆一样，是各个线程共享的内存区域。</li>
<li>方法区在 JVM 启动的时候被创建，并且它的实际的物理内存空间中和 Java 堆区一样都可以是不连续的。</li>
<li>方法区的大小，跟堆空间一样，可以选择固定大小或者可扩展。</li>
<li>方法区的大小决定了系统可以保存多少个类，如果系统定义了太多的类，导致方法区溢出，虚拟机同样会抛出内存溢出错误: <code>java.lang.OutOfMemoryError: PermGen space</code> 或者 <code>java.lang.OutOfMemoryError: Metaspace</code><ul>
<li>加载大量第三方的 jar 包；Tomcat 部署的工程过多（30-50）个；大量动态的生产反射类</li>
</ul>
</li>
<li>关闭 JVM 就会释放这个区域的内存。</li>
</ul>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MethodAreaDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"start..."</span>);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">1000000</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"end..."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>上面这段简单的代码，运行的时候会加载多少个类呢？</p>
<p><img src="/2020/07/17/JVM-05/LoadedClassesNumber.png" alt="Visual VM"></p>
<p>运行程序，使用 Visual VM 的 Sampler 查看发现如此简单的几句代码执行时竟然加载了一千五百多个类。</p>
<h3 id="HotSpot中方法区的演进"><a href="#HotSpot中方法区的演进" class="headerlink" title="HotSpot中方法区的演进"></a>HotSpot中方法区的演进</h3><ul>
<li>在 jdk7 及以前，习惯上把方法区，称为永久代。jdk8 开始，使用元空间取代了永久代。</li>
<li>本质上，方法区和永久代并不等价。仅是对 Hotspot 而言的。《Java 虚拟机规范》对如何实现方法区，不做统一要求。例如: BEA JRockit &#x2F; IBM J9 中不存在永久代的概念。<ul>
<li>➢ 现在来看，当年使用永久代，不是好的 idea。导致 Java 程序更容易 <code>OOM</code> (超过 <code>-XX:MaxPermSize</code> 上限)</li>
</ul>
</li>
</ul>
<p><img src="/2020/07/17/JVM-05/%E6%96%B9%E6%B3%95%E5%8C%BA1.svg" alt="方法区概述"></p>
<p>而到了 JDK 8 ，终于完全废弃了永久代的概念，该用与 JRockit、J9 一样在本地内存中实现的元空间（Metaspace）来代替</p>
<p>元空间的本质和永久代类似，都是对 JVM 规范中的方法区的实现 。不过元空间与永久代最大的区别在于；<strong>元空间不在虚拟机设置的内存中，而是使用本地内存</strong>。</p>
<p>永久代、元空间二者并不只是名字变了，内部机构也调整了。</p>
<p>根据《Java 虚拟机规范》的规定，如果方法区无法满足新的内存分配需求时，将 抛出 OOM 异常。</p>
<hr>
<h2 id="3-设置方法区大小与OOM"><a href="#3-设置方法区大小与OOM" class="headerlink" title="3 设置方法区大小与OOM"></a>3 设置方法区大小与OOM</h2><p>方法区的大小不必是固定的，jvm 可以根据应用的需要动态调整。</p>
<ul>
<li>jdk7 及以前:<ul>
<li>➢ 通过 <code>-XX:PermSize</code> 来设置永久代初始分配空间。默认值是 20.75M</li>
<li>➢ <code>-XX:MaxPermSize</code> 来设定永久代最大可分配空间。32 位机器默认是 64M， 64 位机器模式是 82M</li>
<li>➢ 当 JVM 加载的类信 息容量超过了这个值，会报异常 <code>OutOfMemoryError : PermGen space</code>。</li>
</ul>
</li>
</ul>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.java;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  测试设置方法区大小参数的默认值</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *  jdk7及以前：</span></span><br><span class="line"><span class="comment"> *  -XX:PermSize=100m -XX:MaxPermSize=100m</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *  jdk8及以后：</span></span><br><span class="line"><span class="comment"> *  -XX:MetaspaceSize=100m  -XX:MaxMetaspaceSize=100m</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> shkstart  shkstart@126.com</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span> 2020  12:16</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MethodAreaDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"start..."</span>);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">1000000</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"end..."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>首先，在 Idea 中将环境调整为 JDK 7:</p>
<ol>
<li>打开 <code>Project Structure</code> - <code>Modules</code> - 选中当前 <code>chapter09</code> , 将 <code>Sources</code> 选项中的 <code>Language Level</code> 调整为 <code>7</code> ;</li>
<li>打开 <code>Run</code> - <code>Edit Configurations</code> ，将 <code>JRE</code> 调整为 <code>JDK7</code> .</li>
</ol>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">  yan  ~/Documents/JVMDemo  jps</span><br><span class="line"><span class="number">90656</span> MethodAreaDemo</span><br><span class="line"><span class="number">59491</span> Main</span><br><span class="line"><span class="number">49030</span></span><br><span class="line"><span class="number">59257</span></span><br><span class="line"><span class="number">91596</span> Jps</span><br><span class="line"><span class="number">90655</span> Launcher</span><br><span class="line">  yan  ~/Documents/JVMDemo  jinfo -flag MetaspaceSize <span class="number">90656</span></span><br><span class="line">no such flag <span class="string">'MetaspaceSize'</span></span><br><span class="line">  yan  ~/Documents/JVMDemo  jinfo -flag PermSize <span class="number">90656</span></span><br><span class="line">-XX:PermSize=<span class="number">21757952</span></span><br></pre></td></tr></table></figure></div>

<p>21757952 &#x2F; 1024 &#x2F; 1024 &#x3D; 20.75 M</p>
<p>然后，将 <code>Language Level</code> 和 <code>JRE</code> 重新设置为 JDK 8，重新运行上面的程序和命令：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">  yan  ~/Documents/JVMDemo  jps</span><br><span class="line"><span class="number">59491</span> Main</span><br><span class="line"><span class="number">91940</span> Jps</span><br><span class="line"><span class="number">91927</span> MethodAreaDemo</span><br><span class="line"><span class="number">49030</span></span><br><span class="line"><span class="number">91926</span> Launcher</span><br><span class="line"><span class="number">59257</span></span><br><span class="line">  yan  ~/Documents/JVMDemo  jinfo -flag PermSize <span class="number">91927</span></span><br><span class="line">no such flag <span class="string">'PermSize'</span></span><br><span class="line">  yan  ~/Documents/JVMDemo  jinfo -flag MetaspaceSize <span class="number">91927</span></span><br><span class="line">-XX:MetaspaceSize=<span class="number">21807104</span></span><br></pre></td></tr></table></figure></div>

<ul>
<li>jdk8 及以后:<ul>
<li>➢ 元数据区大小可以使用参数 <code>-XX:MetaspaceSize</code> 和 <code>-XX:MaxMetaspaceSize</code> 指定，替代上述原有的两个参数。</li>
<li>➢ 默认值依赖于平台。windows 下，<code>-XX:MetaspaceSize</code> 是 21M， <code>-XX:MaxMetaspaceSize</code> 的值是 - 1，即没有限制。</li>
<li>➢ 与永久代不同，如果不指定大小，默认情况下，虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出，虚拟机一样会拋出异常 <code>OutOfMemoryError: Metaspace</code></li>
<li>➢ <code>-XX:MetaspaceSize</code> : 设置初始的元空间大小。 对于一个 64 位的服务器端 JVM 来说，其默认的 <code>-XX:MetaspaceSize</code> 值为 21MB. 这就是初始的高水位线，一旦触及这个水位线，Full GC 将会被触发并卸载没用的类 (即这些类对应的类加载器不再存活)，然后这个高水位线将会重置。新的高水位线的值取决于 GC 后释放了多少元空间。如果释放的空间不足，那么在不超过 <code>MaxMetaspaceSize</code> 时，适当提高该值。如果释放空间过多，则适当降低该值。</li>
<li>➢ 如果初始化的高水位线设置过低， 上述高水位线调整情况会发生很多次。 通过垃圾回收器的日志可以观察到 Full GC 多次调用。为了避免频繁地 GC，建议将 <code>XX:MetaspaceSize</code> 设置为一个相对较高的值。</li>
</ul>
</li>
</ul>
<p>OOMTest:</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter;</span><br><span class="line"><span class="keyword">import</span> jdk.internal.org.objectweb.asm.Opcodes;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * jdk6/7中：</span></span><br><span class="line"><span class="comment"> * -XX:PermSize=10m -XX:MaxPermSize=10m</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * jdk8中：</span></span><br><span class="line"><span class="comment"> * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> shkstart  shkstart@126.com</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span> 2020  22:24</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OOMTest</span> <span class="keyword">extends</span> <span class="title">ClassLoader</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> j = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            OOMTest test = <span class="keyword">new</span> OOMTest();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">                <span class="comment">//创建ClassWriter对象，用于生成类的二进制字节码</span></span><br><span class="line">                ClassWriter classWriter = <span class="keyword">new</span> ClassWriter(<span class="number">0</span>);</span><br><span class="line">                <span class="comment">//指明版本号，修饰符，类名，包名，父类，接口</span></span><br><span class="line">                classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, <span class="string">"Class"</span> + i, <span class="keyword">null</span>, <span class="string">"java/lang/Object"</span>, <span class="keyword">null</span>);</span><br><span class="line">                <span class="comment">//返回byte[]</span></span><br><span class="line">                <span class="keyword">byte</span>[] code = classWriter.toByteArray();</span><br><span class="line">                <span class="comment">//类的加载</span></span><br><span class="line">                test.defineClass(<span class="string">"Class"</span> + i, code, <span class="number">0</span>, code.length);<span class="comment">//Class对象</span></span><br><span class="line">                j++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(j);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<iframe width="1665" height="596" src="https://www.youtube.com/embed/2jNi1siWLn0?list=PLtGk8Nqe2ZcK0xUtbQjHeX2gqgoOdKJnX" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<p><strong>如何解决这些OOM</strong>？（涉及调优，以后细说）</p>
<ol>
<li>要解决 OOM 异常或 heap space 的异常，一般的手段是首先通过内存映像分析工具 (如 Eclipse Memory Analyzer) 对 dump 出来的堆转储快照进行分析，重点是确认内存中的对象是否是必要的，也就是要先分清楚到底是出现了内存泄漏 (Memory Leak) 还是内存溢出 (Memory overflow)。</li>
<li>如果是内存泄漏，可进一步通过工具查看泄漏对象到 GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与 GCRoots 相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息，以及 GC Roots 引用链的信息，就可以比较准确地定位出泄漏代码的位置。</li>
<li>如果不存在内存泄漏，换句话说就是内存中的对象确实都还必须存活着，那就应当检查虚拟机的堆参数 (<code>-Xmx</code> 与 <code>-Xms</code>) ，与机器物理内存对比看是否还可以调大，从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况，尝试减少程序运行期的内存消耗。</li>
</ol>
<hr>
<h2 id="4-方法区的内部结构"><a href="#4-方法区的内部结构" class="headerlink" title="4 方法区的内部结构"></a>4 方法区的内部结构</h2><p><img src="/2020/07/17/JVM-05/%E6%96%B9%E6%B3%95%E5%8C%BA2.svg" alt="方法区内部结构简图"></p>
<h3 id="方法区-Method-Area-存储什么"><a href="#方法区-Method-Area-存储什么" class="headerlink" title="方法区 (Method Area) 存储什么"></a>方法区 (Method Area) 存储什么</h3><p>《深入理解 Java 虛拟机》书中对方法区 (Method Area) 存储内容描述如下:<br>它用于存储已被虚拟机加载的 <strong>类型信息、常量、静态变量、即时编译器编译后的代码缓存</strong> 等。</p>
<h4 id="类型信息"><a href="#类型信息" class="headerlink" title="类型信息"></a>类型信息</h4><p>对每个加载的类型 (类 class、接口 interface、枚举 enum、注解 annotation)，JVM 必须在方法区中存储以下类型信息:</p>
<ul>
<li>①这个类型的完整有效名称 (全名 &#x3D; 包名。类名)</li>
<li>②这个类型直接父类的完整有效名 (对于 interface 或是 java. lang .object，都没有父类)</li>
<li>③这个类型的修饰符 (public, abstract, final 的某个子集)</li>
<li>④这个类型直接接口的一个有序列表</li>
</ul>
<h4 id="域-Field-信息"><a href="#域-Field-信息" class="headerlink" title="域 (Field) 信息"></a>域 (Field) 信息</h4><ul>
<li>JVM 必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。</li>
<li>域的相关信息包括：域名称、域类型、域修饰符 (public, private,protected, static, final, <em>volatile</em>, <em>transient</em> 的某个子集)</li>
</ul>
<h4 id="方法-Method-信息"><a href="#方法-Method-信息" class="headerlink" title="方法 (Method) 信息"></a>方法 (Method) 信息</h4><p>JVM 必须保存所有方法的以下信息，同域信息 - - 样包括声明顺序:</p>
<ul>
<li>方法名称</li>
<li>方法的返回类型 (或 void)</li>
<li>方法参数的数量和类型 (按顺序)</li>
<li>方法的修饰符 (public, private, protected， static, final,synchronized, native, abstract 的一个子集)</li>
<li>方法的字节码 (bytecodes)、 操作数栈、局部变量表及大小 (abstract 和 native 方法除外)</li>
<li>异常表 (abstract 和 native 方法除外)<ul>
<li>➢ 每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引</li>
</ul>
</li>
</ul>
<h4 id="字节码角度举例查看"><a href="#字节码角度举例查看" class="headerlink" title="字节码角度举例查看"></a>字节码角度举例查看</h4><div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 测试方法区的内部构成</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> shkstart  shkstart@126.com</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span> 2020  23:39</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MethodInnerStrucTest</span> <span class="keyword">extends</span> <span class="title">Object</span> <span class="keyword">implements</span> <span class="title">Comparable</span>&lt;<span class="title">String</span>&gt;,<span class="title">Serializable</span> </span>&#123;</span><br><span class="line">    <span class="comment">//属性</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> num = <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String str = <span class="string">"测试方法的内部结构"</span>;</span><br><span class="line">    <span class="comment">//构造器</span></span><br><span class="line">    <span class="comment">//方法</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">20</span>;</span><br><span class="line">        System.out.println(<span class="string">"count = "</span> + count);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">test2</span><span class="params">(<span class="keyword">int</span> cal)</span></span>&#123;</span><br><span class="line">        <span class="keyword">int</span> result = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">int</span> value = <span class="number">30</span>;</span><br><span class="line">            result = value / cal;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(String o)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><code>javap</code> 解析字节码文件：<code>javap -v -p MethodInnerStrucTest.class &gt; a2.txt</code></p>
<p>加 <code>-p</code> 参数的原因是显示使用 <code>private</code> 修饰符修饰的内容</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br></pre></td><td class="code"><pre><span class="line">Classfile /Users/yan/Documents/JVMDemo/out/production/chapter09/com/atguigu/java/MethodInnerStrucTest<span class="class">.<span class="keyword">class</span></span></span><br><span class="line"><span class="class">  <span class="title">Last</span> <span class="title">modified</span> 2020年7月26日</span>; size <span class="number">1626</span> bytes</span><br><span class="line">  SHA-<span class="number">256</span> checksum <span class="number">0</span>d22603b5d8e755868a46a34db2d475555262f6854e1941535d1d232314ff9bb</span><br><span class="line">  Compiled from <span class="string">"MethodInnerStrucTest.java"</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">com</span>.<span class="title">atguigu</span>.<span class="title">java</span>.<span class="title">MethodInnerStrucTest</span> <span class="keyword">extends</span> <span class="title">java</span>.<span class="title">lang</span>.<span class="title">Object</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">lang</span>.<span class="title">Comparable</span>&lt;<span class="title">java</span>.<span class="title">lang</span>.<span class="title">String</span>&gt;, <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: (<span class="number">0x0021</span>) ACC_PUBLIC, ACC_SUPER</span><br><span class="line">  this_class: #17                         // com/atguigu/java/MethodInnerStrucTest</span><br><span class="line">  super_class: #18                        // java/lang/Object</span><br><span class="line">  interfaces: <span class="number">2</span>, fields: <span class="number">2</span>, methods: <span class="number">6</span>, attributes: <span class="number">2</span></span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #18.#52        // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Fieldref           #17.#53        // com/atguigu/java/MethodInnerStrucTest.num:I</span><br><span class="line">   #3 = Fieldref           #54.#55        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">   #4 = Class              #56            // java/lang/StringBuilder</span><br><span class="line">   #5 = Methodref          #4.#52         // java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">   #6 = String             #57            // count =</span><br><span class="line">   #7 = Methodref          #4.#58         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">   #8 = Methodref          #4.#59         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">   #9 = Methodref          #4.#60         // java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">  #10 = Methodref          #61.#62        // java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">  #11 = Class              #63            // java/lang/Exception</span><br><span class="line">  #12 = Methodref          #11.#64        // java/lang/Exception.printStackTrace:()V</span><br><span class="line">  #13 = Class              #65            // java/lang/String</span><br><span class="line">  #14 = Methodref          #17.#66        // com/atguigu/java/MethodInnerStrucTest.compareTo:(Ljava/lang/String;)I</span><br><span class="line">  #15 = String             #67            // 测试方法的内部结构</span><br><span class="line">  #16 = Fieldref           #17.#68        // com/atguigu/java/MethodInnerStrucTest.str:Ljava/lang/String;</span><br><span class="line">  #17 = Class              #69            // com/atguigu/java/MethodInnerStrucTest</span><br><span class="line">  #18 = Class              #70            // java/lang/Object</span><br><span class="line">  #19 = Class              #71            // java/lang/Comparable</span><br><span class="line">  #20 = Class              #72            // java/io/Serializable</span><br><span class="line">  #21 = Utf8               num</span><br><span class="line">  #22 = Utf8               I</span><br><span class="line">  #23 = Utf8               str</span><br><span class="line">  #24 = Utf8               Ljava/lang/String;</span><br><span class="line">  #25 = Utf8               &lt;init&gt;</span><br><span class="line">  #26 = Utf8               ()V</span><br><span class="line">  #27 = Utf8               Code</span><br><span class="line">  #28 = Utf8               LineNumberTable</span><br><span class="line">  #29 = Utf8               LocalVariableTable</span><br><span class="line">  #30 = Utf8               this</span><br><span class="line">  #31 = Utf8               Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">  #32 = Utf8               test1</span><br><span class="line">  #33 = Utf8               count</span><br><span class="line">  #34 = Utf8               test2</span><br><span class="line">  #35 = Utf8               (I)I</span><br><span class="line">  #36 = Utf8               value</span><br><span class="line">  #37 = Utf8               e</span><br><span class="line">  #38 = Utf8               Ljava/lang/Exception;</span><br><span class="line">  #39 = Utf8               cal</span><br><span class="line">  #40 = Utf8               result</span><br><span class="line">  #41 = Utf8               StackMapTable</span><br><span class="line">  #42 = Class              #63            // java/lang/Exception</span><br><span class="line">  #43 = Utf8               compareTo</span><br><span class="line">  #44 = Utf8               (Ljava/lang/String;)I</span><br><span class="line">  #45 = Utf8               o</span><br><span class="line">  #46 = Utf8               (Ljava/lang/Object;)I</span><br><span class="line">  #47 = Utf8               &lt;clinit&gt;</span><br><span class="line">  #48 = Utf8               Signature</span><br><span class="line">  #49 = Utf8               Ljava/lang/Object;Ljava/lang/Comparable&lt;Ljava/lang/String;&gt;;Ljava/io/Serializable;</span><br><span class="line">  #50 = Utf8               SourceFile</span><br><span class="line">  #51 = Utf8               MethodInnerStrucTest.java</span><br><span class="line">  #52 = NameAndType        #25:#26        // "&lt;init&gt;":()V</span><br><span class="line">  #53 = NameAndType        #21:#22        // num:I</span><br><span class="line">  #54 = Class              #73            // java/lang/System</span><br><span class="line">  #55 = NameAndType        #74:#75        // out:Ljava/io/PrintStream;</span><br><span class="line">  #56 = Utf8               java/lang/StringBuilder</span><br><span class="line">  #57 = Utf8               count =</span><br><span class="line">  #58 = NameAndType        #76:#77        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #59 = NameAndType        #76:#78        // append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">  #60 = NameAndType        #79:#80        // toString:()Ljava/lang/String;</span><br><span class="line">  #61 = Class              #81            // java/io/PrintStream</span><br><span class="line">  #62 = NameAndType        #82:#83        // println:(Ljava/lang/String;)V</span><br><span class="line">  #63 = Utf8               java/lang/Exception</span><br><span class="line">  #64 = NameAndType        #84:#26        // printStackTrace:()V</span><br><span class="line">  #65 = Utf8               java/lang/String</span><br><span class="line">  #66 = NameAndType        #43:#44        // compareTo:(Ljava/lang/String;)I</span><br><span class="line">  #67 = Utf8               测试方法的内部结构</span><br><span class="line">  #68 = NameAndType        #23:#24        // str:Ljava/lang/String;</span><br><span class="line">  #69 = Utf8               com/atguigu/java/MethodInnerStrucTest</span><br><span class="line">  #70 = Utf8               java/lang/Object</span><br><span class="line">  #71 = Utf8               java/lang/Comparable</span><br><span class="line">  #72 = Utf8               java/io/Serializable</span><br><span class="line">  #73 = Utf8               java/lang/System</span><br><span class="line">  #74 = Utf8               out</span><br><span class="line">  #75 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #76 = Utf8               append</span><br><span class="line">  #77 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #78 = Utf8               (I)Ljava/lang/StringBuilder;</span><br><span class="line">  #79 = Utf8               toString</span><br><span class="line">  #80 = Utf8               ()Ljava/lang/String;</span><br><span class="line">  #81 = Utf8               java/io/PrintStream</span><br><span class="line">  #82 = Utf8               println</span><br><span class="line">  #83 = Utf8               (Ljava/lang/String;)V</span><br><span class="line">  #84 = Utf8               printStackTrace</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">int</span> num;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: (<span class="number">0x0001</span>) ACC_PUBLIC</span><br><span class="line"></span><br><span class="line">  <span class="keyword">private</span> <span class="keyword">static</span> java.lang.String str;</span><br><span class="line">    descriptor: Ljava/lang/String;</span><br><span class="line">    flags: (<span class="number">0x000a</span>) ACC_PRIVATE, ACC_STATIC</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> com.atguigu.java.MethodInnerStrucTest();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0001</span>) ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: aload_0</span><br><span class="line">         <span class="number">5</span>: bipush        <span class="number">10</span></span><br><span class="line">         7: putfield      #2                  // Field num:I</span><br><span class="line">        <span class="number">10</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">10</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">4</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">11</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0001</span>) ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">3</span>, locals=<span class="number">2</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: bipush        <span class="number">20</span></span><br><span class="line">         <span class="number">2</span>: istore_1</span><br><span class="line">         3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">         6: new           #4                  // class java/lang/StringBuilder</span><br><span class="line">         <span class="number">9</span>: dup</span><br><span class="line">        10: invokespecial #5                  // Method java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">        13: ldc           #6                  // String count =</span><br><span class="line">        15: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">        <span class="number">18</span>: iload_1</span><br><span class="line">        19: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">        22: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">        25: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">        <span class="number">28</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">17</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">18</span>: <span class="number">3</span></span><br><span class="line">        line <span class="number">19</span>: <span class="number">28</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">29</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">            <span class="number">3</span>      <span class="number">26</span>     <span class="number">1</span> count   I</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">test2</span><span class="params">(<span class="keyword">int</span>)</span></span>;</span><br><span class="line">    descriptor: (I)I</span><br><span class="line">    flags: (<span class="number">0x0009</span>) ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">3</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: iconst_0</span><br><span class="line">         <span class="number">1</span>: istore_1</span><br><span class="line">         <span class="number">2</span>: bipush        <span class="number">30</span></span><br><span class="line">         <span class="number">4</span>: istore_2</span><br><span class="line">         <span class="number">5</span>: iload_2</span><br><span class="line">         <span class="number">6</span>: iload_0</span><br><span class="line">         <span class="number">7</span>: idiv</span><br><span class="line">         <span class="number">8</span>: istore_1</span><br><span class="line">         <span class="number">9</span>: goto          <span class="number">17</span></span><br><span class="line">        <span class="number">12</span>: astore_2</span><br><span class="line">        <span class="number">13</span>: aload_2</span><br><span class="line">        14: invokevirtual #12                 // Method java/lang/Exception.printStackTrace:()V</span><br><span class="line">        <span class="number">17</span>: iload_1</span><br><span class="line">        <span class="number">18</span>: ireturn</span><br><span class="line">      Exception table:</span><br><span class="line">         from    to  target type</span><br><span class="line">             <span class="number">2</span>     <span class="number">9</span>    <span class="number">12</span>   Class java/lang/Exception</span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">21</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">23</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">24</span>: <span class="number">5</span></span><br><span class="line">        line <span class="number">27</span>: <span class="number">9</span></span><br><span class="line">        line <span class="number">25</span>: <span class="number">12</span></span><br><span class="line">        line <span class="number">26</span>: <span class="number">13</span></span><br><span class="line">        line <span class="number">28</span>: <span class="number">17</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">5</span>       <span class="number">4</span>     <span class="number">2</span> value   I</span><br><span class="line">           <span class="number">13</span>       <span class="number">4</span>     <span class="number">2</span>     e   Ljava/lang/Exception;</span><br><span class="line">            <span class="number">0</span>      <span class="number">19</span>     <span class="number">0</span>   cal   I</span><br><span class="line">            <span class="number">2</span>      <span class="number">17</span>     <span class="number">1</span> result   I</span><br><span class="line">      StackMapTable: number_of_entries = <span class="number">2</span></span><br><span class="line">        frame_type = <span class="number">255</span> <span class="comment">/* full_frame */</span></span><br><span class="line">          offset_delta = <span class="number">12</span></span><br><span class="line">          locals = [ <span class="keyword">int</span>, <span class="keyword">int</span> ]</span><br><span class="line">          stack = [ class java/lang/Exception ]</span><br><span class="line">        frame_type = <span class="number">4</span> <span class="comment">/* same */</span></span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(java.lang.String)</span></span>;</span><br><span class="line">    descriptor: (Ljava/lang/String;)I</span><br><span class="line">    flags: (<span class="number">0x0001</span>) ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">2</span>, args_size=<span class="number">2</span></span><br><span class="line">         <span class="number">0</span>: iconst_0</span><br><span class="line">         <span class="number">1</span>: ireturn</span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">33</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">2</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">            <span class="number">0</span>       <span class="number">2</span>     <span class="number">1</span>     o   Ljava/lang/String;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(java.lang.Object)</span></span>;</span><br><span class="line">    descriptor: (Ljava/lang/Object;)I</span><br><span class="line">    flags: (<span class="number">0x1041</span>) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">2</span>, args_size=<span class="number">2</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         <span class="number">1</span>: aload_1</span><br><span class="line">         2: checkcast     #13                 // class java/lang/String</span><br><span class="line">         5: invokevirtual #14                 // Method compareTo:(Ljava/lang/String;)I</span><br><span class="line">         <span class="number">8</span>: ireturn</span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">10</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">9</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> &#123;&#125;;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0008</span>) ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">0</span>, args_size=<span class="number">0</span></span><br><span class="line">         0: ldc           #15                 // String 测试方法的内部结构</span><br><span class="line">         2: putstatic     #16                 // Field str:Ljava/lang/String;</span><br><span class="line">         <span class="number">5</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">13</span>: <span class="number">0</span></span><br><span class="line">&#125;</span><br><span class="line">Signature: #49                          // Ljava/lang/Object;Ljava/lang/Comparable&lt;Ljava/lang/String;&gt;;Ljava/io/Serializable;</span><br><span class="line">SourceFile: <span class="string">"MethodInnerStrucTest.java"</span></span><br></pre></td></tr></table></figure></div>

<h3 id="non-final-的类变量"><a href="#non-final-的类变量" class="headerlink" title="non-final 的类变量"></a>non-final 的类变量</h3><ul>
<li>静态变量和类关联在一起，随着类的加载而加载，它们成为类数据在逻辑上的一部分。</li>
<li>类变量被类的所有实例共享，即使没有类的实例时也可以访问它。</li>
</ul>
<p>比如下面的代码：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.java;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * non-final的类变量</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> shkstart  shkstart@126.com</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span> 2020  20:37</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MethodAreaTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Order order = <span class="keyword">null</span>;</span><br><span class="line">        order.hello();</span><br><span class="line">        System.out.println(order.count);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Order</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> count = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> number = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">hello</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"hello!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在执行时是不会报空指针异常的。其编译后生成的字节码文件中实际上是直接调用的类的静态方法和静态变量。</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br></pre></td><td class="code"><pre><span class="line">Classfile /Users/yan/Documents/JVMDemo/out/production/chapter09/com/atguigu/java/MethodAreaTest<span class="class">.<span class="keyword">class</span></span></span><br><span class="line"><span class="class">  <span class="title">Last</span> <span class="title">modified</span> 2020年7月23日</span>; size <span class="number">676</span> bytes</span><br><span class="line">  SHA-<span class="number">256</span> checksum <span class="number">807</span>cacb27b90d94a2df4bb43df8748ef47e8e0304335d36100cb97d1f0c964a0</span><br><span class="line">  Compiled from <span class="string">"MethodAreaTest.java"</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">com</span>.<span class="title">atguigu</span>.<span class="title">java</span>.<span class="title">MethodAreaTest</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: (<span class="number">0x0021</span>) ACC_PUBLIC, ACC_SUPER</span><br><span class="line">  this_class: #6                          // com/atguigu/java/MethodAreaTest</span><br><span class="line">  super_class: #7                         // java/lang/Object</span><br><span class="line">  interfaces: <span class="number">0</span>, fields: <span class="number">0</span>, methods: <span class="number">2</span>, attributes: <span class="number">1</span></span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #7.#23         // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Methodref          #24.#25        // com/atguigu/java/Order.hello:()V</span><br><span class="line">   #3 = Fieldref           #26.#27        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">   #4 = Fieldref           #24.#28        // com/atguigu/java/Order.count:I</span><br><span class="line">   #5 = Methodref          #29.#30        // java/io/PrintStream.println:(I)V</span><br><span class="line">   #6 = Class              #31            // com/atguigu/java/MethodAreaTest</span><br><span class="line">   #7 = Class              #32            // java/lang/Object</span><br><span class="line">   #8 = Utf8               &lt;init&gt;</span><br><span class="line">   #9 = Utf8               ()V</span><br><span class="line">  #10 = Utf8               Code</span><br><span class="line">  #11 = Utf8               LineNumberTable</span><br><span class="line">  #12 = Utf8               LocalVariableTable</span><br><span class="line">  #13 = Utf8               this</span><br><span class="line">  #14 = Utf8               Lcom/atguigu/java/MethodAreaTest;</span><br><span class="line">  #15 = Utf8               main</span><br><span class="line">  #16 = Utf8               ([Ljava/lang/String;)V</span><br><span class="line">  #17 = Utf8               args</span><br><span class="line">  #18 = Utf8               [Ljava/lang/String;</span><br><span class="line">  #19 = Utf8               order</span><br><span class="line">  #20 = Utf8               Lcom/atguigu/java/Order;</span><br><span class="line">  #21 = Utf8               SourceFile</span><br><span class="line">  #22 = Utf8               MethodAreaTest.java</span><br><span class="line">  #23 = NameAndType        #8:#9          // "&lt;init&gt;":()V</span><br><span class="line">  #24 = Class              #33            // com/atguigu/java/Order</span><br><span class="line">  #25 = NameAndType        #34:#9         // hello:()V</span><br><span class="line">  #26 = Class              #35            // java/lang/System</span><br><span class="line">  #27 = NameAndType        #36:#37        // out:Ljava/io/PrintStream;</span><br><span class="line">  #28 = NameAndType        #38:#39        // count:I</span><br><span class="line">  #29 = Class              #40            // java/io/PrintStream</span><br><span class="line">  #30 = NameAndType        #41:#42        // println:(I)V</span><br><span class="line">  #31 = Utf8               com/atguigu/java/MethodAreaTest</span><br><span class="line">  #32 = Utf8               java/lang/Object</span><br><span class="line">  #33 = Utf8               com/atguigu/java/Order</span><br><span class="line">  #34 = Utf8               hello</span><br><span class="line">  #35 = Utf8               java/lang/System</span><br><span class="line">  #36 = Utf8               out</span><br><span class="line">  #37 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #38 = Utf8               count</span><br><span class="line">  #39 = Utf8               I</span><br><span class="line">  #40 = Utf8               java/io/PrintStream</span><br><span class="line">  #41 = Utf8               println</span><br><span class="line">  #42 = Utf8               (I)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> com.atguigu.java.MethodAreaTest();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0001</span>) ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">8</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcom/atguigu/java/MethodAreaTest;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(java.lang.String[])</span></span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: (<span class="number">0x0009</span>) ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">2</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aconst_null</span><br><span class="line">         <span class="number">1</span>: astore_1</span><br><span class="line">         <span class="number">2</span>: aload_1</span><br><span class="line">         <span class="number">3</span>: pop</span><br><span class="line">         4: invokestatic  #2                  // Method com/atguigu/java/Order.hello:()V</span><br><span class="line">         7: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">10</span>: aload_1</span><br><span class="line">        <span class="number">11</span>: pop</span><br><span class="line">        12: getstatic     #4                  // Field com/atguigu/java/Order.count:I</span><br><span class="line">        15: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line">        <span class="number">18</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">10</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">11</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">7</span></span><br><span class="line">        line <span class="number">13</span>: <span class="number">18</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">19</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line">            <span class="number">2</span>      <span class="number">17</span>     <span class="number">1</span> order   Lcom/atguigu/java/Order;</span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"MethodAreaTest.java"</span></span><br></pre></td></tr></table></figure></div>

<h3 id="补充说明：全局常量：final-static"><a href="#补充说明：全局常量：final-static" class="headerlink" title="补充说明：全局常量：final static"></a>补充说明：全局常量：<code>final static</code></h3><p>被声明为 <code>final</code> 的类变量的处理方法则不同，每个全局常量在编译的时候就会被分配了。</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br></pre></td><td class="code"><pre><span class="line">Classfile /Users/yan/Documents/JVMDemo/out/production/chapter09/com/atguigu/java/Order<span class="class">.<span class="keyword">class</span></span></span><br><span class="line"><span class="class">  <span class="title">Last</span> <span class="title">modified</span> 2020年7月23日</span>; size <span class="number">615</span> bytes</span><br><span class="line">  SHA-<span class="number">256</span> checksum d47aa5a5154fe954fcf79b1b36e77c54565d5b454e89e8d545a0bb0d97d2e749</span><br><span class="line">  Compiled from <span class="string">"MethodAreaTest.java"</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">com</span>.<span class="title">atguigu</span>.<span class="title">java</span>.<span class="title">Order</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: (<span class="number">0x0020</span>) ACC_SUPER</span><br><span class="line">  this_class: #6                          // com/atguigu/java/Order</span><br><span class="line">  super_class: #7                         // java/lang/Object</span><br><span class="line">  interfaces: <span class="number">0</span>, fields: <span class="number">2</span>, methods: <span class="number">3</span>, attributes: <span class="number">1</span></span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #7.#24         // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Fieldref           #25.#26        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">   #3 = String             #27            // hello!</span><br><span class="line">   #4 = Methodref          #28.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">   #5 = Fieldref           #6.#30         // com/atguigu/java/Order.count:I</span><br><span class="line">   #6 = Class              #31            // com/atguigu/java/Order</span><br><span class="line">   #7 = Class              #32            // java/lang/Object</span><br><span class="line">   #8 = Utf8               count</span><br><span class="line">   #9 = Utf8               I</span><br><span class="line">  #10 = Utf8               number</span><br><span class="line">  #11 = Utf8               ConstantValue</span><br><span class="line">  #12 = Integer            2</span><br><span class="line">  #13 = Utf8               &lt;init&gt;</span><br><span class="line">  #14 = Utf8               ()V</span><br><span class="line">  #15 = Utf8               Code</span><br><span class="line">  #16 = Utf8               LineNumberTable</span><br><span class="line">  #17 = Utf8               LocalVariableTable</span><br><span class="line">  #18 = Utf8               this</span><br><span class="line">  #19 = Utf8               Lcom/atguigu/java/Order;</span><br><span class="line">  #20 = Utf8               hello</span><br><span class="line">  #21 = Utf8               &lt;clinit&gt;</span><br><span class="line">  #22 = Utf8               SourceFile</span><br><span class="line">  #23 = Utf8               MethodAreaTest.java</span><br><span class="line">  #24 = NameAndType        #13:#14        // "&lt;init&gt;":()V</span><br><span class="line">  #25 = Class              #33            // java/lang/System</span><br><span class="line">  #26 = NameAndType        #34:#35        // out:Ljava/io/PrintStream;</span><br><span class="line">  #27 = Utf8               hello!</span><br><span class="line">  #28 = Class              #36            // java/io/PrintStream</span><br><span class="line">  #29 = NameAndType        #37:#38        // println:(Ljava/lang/String;)V</span><br><span class="line">  #30 = NameAndType        #8:#9          // count:I</span><br><span class="line">  #31 = Utf8               com/atguigu/java/Order</span><br><span class="line">  #32 = Utf8               java/lang/Object</span><br><span class="line">  #33 = Utf8               java/lang/System</span><br><span class="line">  #34 = Utf8               out</span><br><span class="line">  #35 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #36 = Utf8               java/io/PrintStream</span><br><span class="line">  #37 = Utf8               println</span><br><span class="line">  #38 = Utf8               (Ljava/lang/String;)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> count;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: (<span class="number">0x0009</span>) ACC_PUBLIC, ACC_STATIC</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> number;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: (<span class="number">0x0019</span>) ACC_PUBLIC, ACC_STATIC, ACC_FINAL</span><br><span class="line">    ConstantValue: <span class="keyword">int</span> <span class="number">2</span></span><br><span class="line"></span><br><span class="line">  com.atguigu.java.Order();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0000</span>)</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">16</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcom/atguigu/java/Order;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">hello</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0009</span>) ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">0</span>, args_size=<span class="number">0</span></span><br><span class="line">         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">         3: ldc           #3                  // String hello!</span><br><span class="line">         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">         <span class="number">8</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">22</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">23</span>: <span class="number">8</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> &#123;&#125;;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: (<span class="number">0x0008</span>) ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">0</span>, args_size=<span class="number">0</span></span><br><span class="line">         <span class="number">0</span>: iconst_1</span><br><span class="line">         1: putstatic     #5                  // Field count:I</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">17</span>: <span class="number">0</span></span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"MethodAreaTest.java"</span></span><br></pre></td></tr></table></figure></div>

<p>从</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> count;</span><br><span class="line">  descriptor: I</span><br><span class="line">  flags: (<span class="number">0x0009</span>) ACC_PUBLIC, ACC_STATIC</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> number;</span><br><span class="line">  descriptor: I</span><br><span class="line">  flags: (<span class="number">0x0019</span>) ACC_PUBLIC, ACC_STATIC, ACC_FINAL</span><br><span class="line">  ConstantValue: <span class="keyword">int</span> <span class="number">2</span></span><br></pre></td></tr></table></figure></div>

<p>可以看出来 <code>static final</code> 的变量在编译时就已经确定好值了，再从</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> &#123;&#125;;</span><br><span class="line">  descriptor: ()V</span><br><span class="line">  flags: (<span class="number">0x0008</span>) ACC_STATIC</span><br><span class="line">  Code:</span><br><span class="line">    stack=<span class="number">1</span>, locals=<span class="number">0</span>, args_size=<span class="number">0</span></span><br><span class="line">       <span class="number">0</span>: iconst_1</span><br><span class="line">       1: putstatic     #5                  // Field count:I</span><br><span class="line">       <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">    LineNumberTable:</span><br><span class="line">      line <span class="number">17</span>: <span class="number">0</span></span><br></pre></td></tr></table></figure></div>

<p>可以看出来仅使用 <code>static</code> 修饰的类变量在类加载时才被初始化变量。实际上上面的代码对应的就是字节码中的 <code>&lt;clinit&gt;()</code> 方法，也就是<a href="https://xiaoyan94.github.io/2020/07/03/JVM-01/#%E5%88%9D%E5%A7%8B%E5%8C%96">类加载的<strong>初始化</strong>阶段</a>。</p>
<h3 id="class-文件中常量池的理解"><a href="#class-文件中常量池的理解" class="headerlink" title="class 文件中常量池的理解"></a>class 文件中常量池的理解</h3><h4 id="运行时常量池-VS-常量池"><a href="#运行时常量池-VS-常量池" class="headerlink" title="运行时常量池 VS 常量池"></a>运行时常量池 VS 常量池</h4><ul>
<li>方法区，内部包含了运行时常量池。</li>
<li>字节码文件中，内部包含了常量池。</li>
<li>要弄清楚方法区，需要理解清除 ClassFile ，因为加载类的信息都在方法区。</li>
<li>要弄清楚方法区的运行时常量池，需要理解清除 ClassFile 中的常量池。</li>
</ul>
<p>一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述信息外，还包含一项信息那就是常量池表 (Constant Pool Table) ，包括各种字面量和对类型、域和方法的符号引用。</p>
<h4 id="为什么需要常量池"><a href="#为什么需要常量池" class="headerlink" title="为什么需要常量池"></a>为什么需要常量池</h4><p>一个 java 源文件中的类、接口，编译后产生一个字节码文件。而 Java 中的字节码需要数据支持，通常这种数据会很大以至于不能直接存到字节码里，换另一种方式，可以存到常量池，这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池，之前有介绍。</p>
<p>比如：如下的代码:</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SimpleClass</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">sayHello</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"hello"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>虽然 <code>SimpleClass.java</code> 只有 194 字节，但是里面却使用了 <code>String</code>、<code>System</code>、<code>PrintStream</code> 及 <code>Object</code> 等结构。这里代码量其实已经很小了。如果代码多，引用到的结构会更多！这里就需要常量池了！</p>
<iframe width="1496" height="809" src="https://www.youtube.com/embed/ybbNRXVaBc8?list=PLtGk8Nqe2ZcK0xUtbQjHeX2gqgoOdKJnX" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<h4 id="常量池中有什么"><a href="#常量池中有什么" class="headerlink" title="常量池中有什么"></a>常量池中有什么</h4><p>几种在常量池内存储的数据类型包括:</p>
<ul>
<li>数量值</li>
<li>字符串值</li>
<li>类引用</li>
<li>字段引用</li>
<li>方法引用</li>
</ul>
<p>例如下面这段代码:</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MethodAreaTest2</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Object obj = <span class="keyword">new</span> Object();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><code>Object foo = new Object();</code></p>
<p>将会被编译成如下字节码:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0:  new #2  // Class java/lang/Object</span><br><span class="line"><span class="number">1</span>:  dup</span><br><span class="line">2:  invokespecial #3    // Method java/lang/Object "&lt;init&gt;"( ) V</span><br></pre></td></tr></table></figure>

<h4 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h4><p>常量池，可以看做是一张表，虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型。</p>
<h3 id="运行时常量池的理解"><a href="#运行时常量池的理解" class="headerlink" title="运行时常量池的理解"></a>运行时常量池的理解</h3><h4 id="运行时常量池"><a href="#运行时常量池" class="headerlink" title="运行时常量池"></a>运行时常量池</h4><ul>
<li>运行时常量池 (Runtime Constant Pool) 是方法区的一部分。</li>
<li>常量池表 ( Constant Pool Table) 是 Class 文件的一部分，<strong>用于存放编译期生成的各种字面量与符号引用，这部分内容将在类加载后存放到方法区的运行时常量池中</strong>。</li>
<li>运行时常量池，在加载类和接口到虛拟机后，就会创建对应的运行时常量池。</li>
<li>JVM 为每个已加载的类型 ( 类或接口) 都维护一个常量池。池中的数据项像数组项一样，是<strong>通过索引访问</strong>的。</li>
<li>运行时常量池中包含多种不同的常量，包括编译期就已经明确的数值字面量，也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了，这里换为真实地址。<ul>
<li>➢ 运行时常量池，相对于 Class 文件常量池的另一重要特征是：<strong>具备动态性</strong>。</li>
</ul>
</li>
<li>运行时常量池类似于传统编程语言中的符号表 (symboltable)，但是它所包含的数据却比符号表要更加丰富一些。</li>
<li>当创建类或接口的运行时常量池时，如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值，则 JVM 会抛 <code>OutOfMemoryError</code> 异常。</li>
</ul>
<hr>
<h2 id="5-方法区使用举例"><a href="#5-方法区使用举例" class="headerlink" title="5 方法区使用举例"></a>5 方法区使用举例</h2><p>图示举例方法区的使用</p>
<iframe width="100%" height="480" src="https://www.youtube.com/embed/icLKv_ENEmE?list=PLtGk8Nqe2ZcK0xUtbQjHeX2gqgoOdKJnX" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<hr>
<h2 id="6-方法区的演进细节"><a href="#6-方法区的演进细节" class="headerlink" title="6 方法区的演进细节"></a>6 方法区的演进细节</h2><ol>
<li><p>首先明确：只有 HotSpot 才有永久代。</p>
<p> BEA JRockit、IBM J9等来说，是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节，不受《Java 虚拟机规范》管束，并不要求统一。</p>
</li>
<li><p>HotSpot 中方法区的变化：</p>
<table>
<thead>
<tr>
<th>0</th>
<th>1</th>
</tr>
</thead>
<tbody><tr>
<td>jdk1.6 及之前</td>
<td>有永久代 (permanent generation) ，静态变量存放在永久代上</td>
</tr>
<tr>
<td>jdk1.7</td>
<td>有永久代，但已经逐步 “去永久代”，字符串常量池、静态变量移除，保存在堆中</td>
</tr>
<tr>
<td>jdk1.8 及之后</td>
<td>无永久代，类型信息、字段、方法、常量保存在本地内存的元空间，但字符串常量池、静态变量仍在堆</td>
</tr>
</tbody></table>
</li>
</ol>
<p><img src="/2020/07/17/JVM-05/HotSpot%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%B8%AD%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E6%BC%94%E8%BF%9B%E7%BB%86%E8%8A%82.svg" alt="HotSpot虚拟机中方法区的演进细节"></p>
<h3 id="永久代为什么要被元空间替换"><a href="#永久代为什么要被元空间替换" class="headerlink" title="永久代为什么要被元空间替换"></a>永久代为什么要被元空间替换</h3><p><a href="http://openjdk.java.net/jeps/122" target="_blank" rel="noopener">http://openjdk.java.net/jeps/122</a> 中关于 Remove the Permanent Generation 的描述：</p>
<blockquote>
<p><strong>Summary</strong><br>Remove the permanent generation from the Hotspot JVM and thus the need to tune the size of the permanent generation.</p>
</blockquote>
<p>从 Hotspot JVM 中删除永久代，因此不需要调整永久代的大小。</p>
<blockquote>
<p><strong>Motivation</strong><br>This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.</p>
</blockquote>
<p>这是 JRockit 和 Hotspot 融合工作的一部分。 JRockit 客户不需要配置永久代（因为 JRockit 没有永久代），并且习惯于不配置永久代。</p>
<p>随着 Java8 的到来，HotSpot VM 中再也见不到永久代了。但是这并不意味着类的元数据信息也消失了。这些数据被移到了一个<strong>与堆不相连的本地内存区域</strong>，这个区域叫做**元空间( Metaspace )**。</p>
<p>由于类的元数据分配在本地内存中，元空间的最大可分配空间就是系统可用内存空间。</p>
<p>这项改动是很有必要的，原因有:</p>
<p>1） <strong>为永久代设置空间大小是很难确定的</strong>。<br>在某些场景下，如果动态加载类过多，容易产生 Perm 区的 OOM。比如某个实际 Web 工程中，因为功能点比较多，在运行过程中，要不断动态加载很多类，经常出现致命错误。<br><code>&quot;Exception in thread &#39;dubbo client x.x connector&#39; java.lang.OutOfMemoryError: PermGen space&quot;</code><br>而元空间和永久代之间最大的区别在于：元空间并不在虚拟机中，而是使用本地内存。<br>因此，默认情况下，元空间的大小仅受本地内存限制。</p>
<p>2） <strong>对永久代进行调优是很困难的</strong>。</p>
<p><a href="#7-%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6">方法区的垃圾回收</a></p>
<h3 id="StringTable为什么要调整位置"><a href="#StringTable为什么要调整位置" class="headerlink" title="StringTable为什么要调整位置"></a>StringTable为什么要调整位置</h3><p>与 Jdk1.6 不同，jdk7 中将 StringTable 放到了堆空间中。因为永久代的回收效率很低，在 full gc 的时候才会触发。而 full gc 是老年代的空间不足、永久代不足时才会触发。</p>
<p>这就导致 StringTable 回收效率不高。而我们开发中会有大量的字符串被创建，回收效率低，导致永久代内存不足。放到堆里，能及时回收内存。</p>
<h3 id="如何证明静态变量存在哪"><a href="#如何证明静态变量存在哪" class="headerlink" title="如何证明静态变量存在哪"></a>如何证明静态变量存在哪</h3><iframe width="1144" height="576" src="https://www.youtube.com/embed/jXWKqUZgQUo?list=PLtGk8Nqe2ZcK0xUtbQjHeX2gqgoOdKJnX" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<p>参考《深入理解 Java 虚拟机》第三版：4.2.1 节</p>
<p>通过实验来回答一个简单问题：staticObj、instanceObj、localObj这三个变量本身（而不是它们所指向的对象）存放在哪里？</p>
<p>代码清单4-6　JHSDB测试代码</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * staticObj、instanceObj、localObj存放在哪里？</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JHSDB_TestCase</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> ObjectHolder staticObj = <span class="keyword">new</span> ObjectHolder();</span><br><span class="line">        ObjectHolder instanceObj = <span class="keyword">new</span> ObjectHolder();</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">void</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            ObjectHolder localObj = <span class="keyword">new</span> ObjectHolder();</span><br><span class="line">            System.out.println(<span class="string">"done"</span>); <span class="comment">// 这里设一个断点</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ObjectHolder</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Test test = <span class="keyword">new</span> JHSDB_TestCase.Test();</span><br><span class="line">        test.foo();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<blockquote>
<p>1.答案读者当然都知道：staticObj随着Test的类型信息存放在方法区，instanceObj随着Test的对象实例存放在Java堆，localObject则是存放在foo()方法栈帧的局部变量表中。这个答案是通过前两章学习的理论知识得出的，现在要做的是通过JHSDB来实践验证这一点。</p>
<p>2.从《Java虚拟机规范》所定义的概念模型来看，所有Class相关的信息都应该存放在方法区之中， 但方法区该如何实现，《Java虚拟机规范》并未做出规定，这就成了一件允许不同虚拟机自己灵活把握的事情。JDK 7及其以后版本的HotSpot虚拟机选择把静态变量与类型在Java语言一端的映射Class对象存放在一起，存储于Java堆之中，从我们的实验中也明确验证了这一点。</p>
<p>3.在JDK 7以前，即还没有开始“去永久代”行动时，这些静态变量是存放在永久代上的，JDK 7起把 静态变量、字符常量这些从永久代移除出去。</p>
</blockquote>
<hr>
<h2 id="7-方法区的垃圾回收"><a href="#7-方法区的垃圾回收" class="headerlink" title="7 方法区的垃圾回收"></a>7 方法区的垃圾回收</h2><p>有些人认为方法区 (如 HotSpot 虚拟机中的元空间或者永久代) 是没有垃圾收集行为的，其实不然。《Java 虚拟机规范》对方法区的约束是非常宽松的，提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在 (如 JDK11 时期的 ZGC 收集器就不支持类卸载)。</p>
<p>一般来说这个区域的回收效果比较难令人满意，尤其是类型的卸载，条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前 Sun 公司的 Bug 列表中，曾出现过的若干个严重的 Bug 就是由于低版本的 HotSpot 虚拟机对此区域未完全回收而导致内存泄漏。</p>
<p><strong>方法区的垃圾收集主要回收两部分内容：常量池中废弃的常量和不再使用的类型</strong>。</p>
<p>● 先来说说方法区内常量池之中主要存放的两大类常量：字面量和符号引用。字面量比较接近 Java 语言层次的常量概念，如文本字符串、被声明为 final 的常量值等。而符号引用则属于编译原理方面的概念，包括下面三类常量:</p>
<ul>
<li>➢ 1、类和接口的全限定名</li>
<li>➢ 2、字段的名称和描述符</li>
<li>➢ 3、方法的名称和描述符</li>
</ul>
<p>● HotSpot 虚拟机对常量池的回收策略是很明确的，只要常量池中的常量没有被任何地方引用，就可以被回收。</p>
<p>● 回收废弃常量与回收 Java 堆中的对象非常类似。</p>
<p>● 判定一个常量是否 “废弃” 还是相对简单，而要判定一个类型是否属于 “不再被使用的类” 的条件就比较苛刻了。需要同时满足下面三个条件:</p>
<ul>
<li>➢ 该类所有的实例都已经被回收，也就是 Java 堆中不存在该类及其任何派生子类的实例。</li>
<li>➢ 加载该类的类加载器已经被回收，这个条件除非是经过精心设计的可替换类加载器的场景，如 OSGi、JSP 的重加载等，否则通常是很难达成的。</li>
<li>➢ 该类对应的 <code>java.lang.Class</code> 对象没有在任何地方被引用，无法在任何地方通过反射访问该类的方法。</li>
</ul>
<p>● Java 虚拟机被允许对满足上述三个条件的无用类进行回收，这里说的仅仅是 “被允许”，而并不是和对象一样，没有引用了就必然会回收。关于是否要对类型进行回收，HotSpot 虚拟机提供了 <code>-Xnoclassgc</code> 参数进行控制，还可以使用 <code>-verbose:class</code> 以及 <code>-XX:+TraceClass-Loading</code>、<code>-XX:+TraceClassUnLoading</code> 查看类加载和卸载信息</p>
<p>● 在大量使用反射、动态代理、CGLib 等字节码框架，动态生成 JSP 以及 OSGi 这类频繁自定义类加载器的场景中，<strong>通常都需要 Java 虚拟机具备类型卸载的能力，以保证不会对方法区造成过大的内存压力</strong>。</p>
<hr>
<h2 id="8-总结"><a href="#8-总结" class="headerlink" title="8 总结"></a>8 总结</h2><p>常见面试题</p>
<p><em>百度</em>:</p>
<ul>
<li>三面：说一下 JVM 内存模型吧，有哪些区？分别干什么的？</li>
</ul>
<p><em>蚂蚁金服</em>:</p>
<ul>
<li>Java8 的内存分代改进</li>
<li>JVM 内存分哪几个区，每个区的作用是什么？</li>
<li>一面: JVM 内存分布 &#x2F; 内存结构？栈和堆的区别？堆的结构？为什么两个 survivor 区？</li>
<li>二面: Eden 和 Survior 的比例分配</li>
</ul>
<p><em>小米</em>:</p>
<ul>
<li>jvm 内存分区，为什么要有新生代和老年代</li>
</ul>
<p><em>字节跳动</em>:</p>
<ul>
<li>二面: Java 的内存分区</li>
<li>二面：讲讲 jvm 运行时数据区</li>
<li>什么时候对象会进入老年代?</li>
</ul>
<p><em>京东</em>:</p>
<ul>
<li>JVM 的内存结构，Eden 和 Survivor 比例。</li>
<li>JVM 内存为什么要分成新生代，老年代，持久代。新生代中为什么要分为 Eden 和 Survivor。</li>
</ul>
<p><em>天猫</em>: .</p>
<ul>
<li>一面: Jvm 内存模型以及分区，需要详细到每个区放什么。</li>
<li>一面: JVM 的内存模型，Java8 做了什么修改</li>
</ul>
<p><em>拼多多</em>:</p>
<ul>
<li>JVM 内存分哪几个区，每个区的作用是什么?</li>
</ul>
<p><em>美团</em>:</p>
<ul>
<li>java 内存分配</li>
<li>jvm 的永久代中会发生垃圾回收吗？</li>
<li>一面: jvm 内存分区，为什么要有新生代和老年代?</li>
</ul>

          
      
    </div>
    
    
      <footer class="article-footer">
        完
      </footer>
    
  </div>
  
    
<nav id="article-nav">
  <div class="article-nav-block">
    
      <a href="../../../08/08/JVM-06/" id="article-nav-newer" class="article-nav-link-wrap">
        <strong class="article-nav-caption"></strong>
        <div class="article-nav-title">
          
            JVM 06 运行时数据区的总结与常见大厂面试题说明
          
        </div>
      </a>
    
  </div>
  <div class="article-nav-block">
    
      <a href="../../11/JVM-04/" id="article-nav-older" class="article-nav-link-wrap">
        <div class="article-nav-title">JVM 04 运行时数据区之堆 (Heap)</div>
        <strong class="article-nav-caption"></strong>
      </a>
    
  </div>
</nav>

    <!-- <link rel="stylesheet" href="/css/gitment.css">  -->
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>

<div id="vcommentsContainer"></div>
<!--引用评论框输入特效js文件-->

<script src="../../../../js/shuru.js"></script>

<script>
  POWERMODE.colorful = true; // make power mode colorful
  POWERMODE.shake = true; // turn off shake
  document.body.addEventListener('input', POWERMODE);
</script>
<!-- valine评论系统 -->
<script>
  new Valine({
      el: '#vcommentsContainer',
      appId: 'AttjBiS7UwxkxjV1CSrNywoi-gzGzoHsz',
      appKey: 'F50aWycFFmAPLC8CfSW7rXdP',
      avatar: 'monsterid',
      enableQQ: true,
      placeholder: '昵称处填QQ号自动抓取网名和邮箱哟~'
  })
</script>


    <!-- <link rel="stylesheet" href="/css/gitment.css"> 
<script src="/js/gitment.js"></script>

<div id="gitmentContainer"></div>

<script>
var gitment = new Gitment({
  owner: '',
  repo: '',
  oauth: {
    client_id: '',
    client_secret: '',
  },
})
gitment.render('gitmentContainer')
</script>

 -->

  
  
</article>
</section>
        <aside id="sidebar">
  
    <div class="widget-box">
  <div class="avatar-box">
    <img class="avatar" src="https://q1.qlogo.cn/g?b=qq&amp;nk=979727728&amp;s=640" title="图片来自QQ"></img>
    <h3 class="avatar-name">
      
        许嵩老公
      
    </h3>
    <p class="avatar-slogan">
      深吸一口梦，吹个气球存起来。
    </p>
  </div>
</div>


  
    

  
    
  <div class="widget-box">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/NET/" rel="tag">.NET</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Cookie/" rel="tag">Cookie</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/ES6/" rel="tag">ES6</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Git-Bash/" rel="tag">Git Bash</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Github/" rel="tag">Github</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Github-Actions/" rel="tag">Github Actions</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/HDFS/" rel="tag">HDFS</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/HTTP/" rel="tag">HTTP</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Hadoop/" rel="tag">Hadoop</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Hexo/" rel="tag">Hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Idea/" rel="tag">Idea</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/JVM/" rel="tag">JVM</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Java/" rel="tag">Java</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/JavaScript/" rel="tag">JavaScript</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Linux/" rel="tag">Linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/MapReduce/" rel="tag">MapReduce</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Markdown/" rel="tag">Markdown</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Maven/" rel="tag">Maven</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Node/" rel="tag">Node</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Node-js/" rel="tag">Node.js</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/SQL/" rel="tag">SQL</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Serial-Port/" rel="tag">Serial Port</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Shell/" rel="tag">Shell</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/SpringBoot/" rel="tag">SpringBoot</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/TCP/" rel="tag">TCP</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/VSCode/" rel="tag">VSCode</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Vue/" rel="tag">Vue</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/WebSocket/" rel="tag">WebSocket</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/YARN/" rel="tag">YARN</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/hexo/" rel="tag">hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/macOS/" rel="tag">macOS</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/ssh/" rel="tag">ssh</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/" rel="tag">中文乱码</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/" rel="tag">大数据</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/" rel="tag">安装教程</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%AF%86%E9%92%A5/" rel="tag">密钥</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%B9%B6%E8%A1%8C%E7%BC%96%E7%A8%8B/" rel="tag">并行编程</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" rel="tag">数据库</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E7%94%B5%E8%84%91/" rel="tag">电脑</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E7%AB%B9%E4%BA%91/" rel="tag">竹云</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E7%BB%88%E7%AB%AF/" rel="tag">终端</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E8%84%9A%E6%9C%AC/" rel="tag">脚本</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E8%BD%AC%E8%BD%BD/" rel="tag">转载</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E8%BD%AF%E4%BB%B6/" rel="tag">软件</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-box">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="../../../../tags/NET/" style="font-size: 10px;">.NET</a> <a href="../../../../tags/Cookie/" style="font-size: 10px;">Cookie</a> <a href="../../../../tags/ES6/" style="font-size: 10px;">ES6</a> <a href="../../../../tags/Git-Bash/" style="font-size: 11.67px;">Git Bash</a> <a href="../../../../tags/Github/" style="font-size: 13.33px;">Github</a> <a href="../../../../tags/Github-Actions/" style="font-size: 10px;">Github Actions</a> <a href="../../../../tags/HDFS/" style="font-size: 10px;">HDFS</a> <a href="../../../../tags/HTTP/" style="font-size: 11.67px;">HTTP</a> <a href="../../../../tags/Hadoop/" style="font-size: 18.33px;">Hadoop</a> <a href="../../../../tags/Hexo/" style="font-size: 10px;">Hexo</a> <a href="../../../../tags/Idea/" style="font-size: 10px;">Idea</a> <a href="../../../../tags/JVM/" style="font-size: 18.33px;">JVM</a> <a href="../../../../tags/Java/" style="font-size: 20px;">Java</a> <a href="../../../../tags/JavaScript/" style="font-size: 16.67px;">JavaScript</a> <a href="../../../../tags/Linux/" style="font-size: 15px;">Linux</a> <a href="../../../../tags/MapReduce/" style="font-size: 11.67px;">MapReduce</a> <a href="../../../../tags/Markdown/" style="font-size: 10px;">Markdown</a> <a href="../../../../tags/Maven/" style="font-size: 13.33px;">Maven</a> <a href="../../../../tags/Node/" style="font-size: 10px;">Node</a> <a href="../../../../tags/Node-js/" style="font-size: 10px;">Node.js</a> <a href="../../../../tags/SQL/" style="font-size: 13.33px;">SQL</a> <a href="../../../../tags/Serial-Port/" style="font-size: 10px;">Serial Port</a> <a href="../../../../tags/Shell/" style="font-size: 11.67px;">Shell</a> <a href="../../../../tags/SpringBoot/" style="font-size: 10px;">SpringBoot</a> <a href="../../../../tags/TCP/" style="font-size: 10px;">TCP</a> <a href="../../../../tags/VSCode/" style="font-size: 10px;">VSCode</a> <a href="../../../../tags/Vue/" style="font-size: 10px;">Vue</a> <a href="../../../../tags/WebSocket/" style="font-size: 11.67px;">WebSocket</a> <a href="../../../../tags/YARN/" style="font-size: 10px;">YARN</a> <a href="../../../../tags/hexo/" style="font-size: 11.67px;">hexo</a> <a href="../../../../tags/macOS/" style="font-size: 11.67px;">macOS</a> <a href="../../../../tags/ssh/" style="font-size: 11.67px;">ssh</a> <a href="../../../../tags/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/" style="font-size: 10px;">中文乱码</a> <a href="../../../../tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/" style="font-size: 10px;">大数据</a> <a href="../../../../tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/" style="font-size: 10px;">安装教程</a> <a href="../../../../tags/%E5%AF%86%E9%92%A5/" style="font-size: 10px;">密钥</a> <a href="../../../../tags/%E5%B9%B6%E8%A1%8C%E7%BC%96%E7%A8%8B/" style="font-size: 10px;">并行编程</a> <a href="../../../../tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" style="font-size: 10px;">数据库</a> <a href="../../../../tags/%E7%94%B5%E8%84%91/" style="font-size: 11.67px;">电脑</a> <a href="../../../../tags/%E7%AB%B9%E4%BA%91/" style="font-size: 11.67px;">竹云</a> <a href="../../../../tags/%E7%BB%88%E7%AB%AF/" style="font-size: 13.33px;">终端</a> <a href="../../../../tags/%E8%84%9A%E6%9C%AC/" style="font-size: 10px;">脚本</a> <a href="../../../../tags/%E8%BD%AC%E8%BD%BD/" style="font-size: 10px;">转载</a> <a href="../../../../tags/%E8%BD%AF%E4%BB%B6/" style="font-size: 10px;">软件</a>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2023/02/">二月 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2023/01/">一月 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2022/11/">十一月 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2022/09/">九月 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2022/08/">八月 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2021/12/">十二月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2021/02/">二月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2021/01/">一月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2020/08/">八月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2020/07/">七月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2020/06/">六月 2020</a></li></ul>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="../../../../2023/02/13/%E4%BD%BF%E7%94%A8Node-js%E5%90%8E%E5%8F%B0%E8%AF%BB%E5%8F%96%E4%B8%B2%E5%8F%A3%E6%95%B0%E6%8D%AE%E5%B9%B6%E9%80%9A%E8%BF%87WebSocket%E5%AE%9E%E6%97%B6%E6%98%BE%E7%A4%BA%E5%9C%A8%E7%BD%91%E9%A1%B5%E4%B8%8A/">使用Node.js后台读取串口数据并通过WebSocket实时显示在网页上</a>
          </li>
        
          <li>
            <a href="../../../../2023/02/09/%E4%BD%9C%E4%B8%BA%E7%94%A8%E6%88%B7%EF%BC%8C%E4%BF%AE%E6%94%B9Cookie%E6%9C%89%E6%95%88%E6%9C%9F%EF%BC%8C%E5%BB%B6%E9%95%BFCookie%E6%9C%9F%E9%99%90/">作为用户，修改Cookie有效期，延长Cookie期限</a>
          </li>
        
          <li>
            <a href="../../../../2023/02/08/%E7%BB%88%E7%AB%AF%E5%91%BD%E4%BB%A4%E4%BB%A3%E7%90%86/">终端命令网络设置</a>
          </li>
        
          <li>
            <a href="../../../../2023/01/18/Windows%E7%B3%BB%E7%BB%9FC%E7%9B%98%E6%B8%85%E7%90%86%E5%B7%A5%E5%85%B7FreeMove%E5%8F%8A%E6%96%87%E4%BB%B6%E5%8D%A0%E7%94%A8%E8%BF%9B%E7%A8%8B%E6%9F%A5%E7%9C%8B%E8%BD%AF%E4%BB%B6LockHunter%E9%85%8D%E5%90%88%E4%BD%BF%E7%94%A8/">Windows系统C盘清理工具FreeMove及文件占用进程查看软件LockHunter配合使用</a>
          </li>
        
          <li>
            <a href="../../../../2023/01/14/AutoReconnectWiFi/">检测断网自动重连WiFi脚本</a>
          </li>
        
      </ul>
    </div>
  </div>

  
      <div class="widget-box">
    <h3 class="widget-title">友链</h3>
    <div class="widget">
      
        <!-- <a style="display: block;" href="../../../../https:/xiaoyan94.github.io/" title target='_blank' -->
        <a style="display: block;" href="https://xiaoyan94.github.io/" title target='_blank'
        >Github Pages</a>
      
        <!-- <a style="display: block;" href="../../../../https:/xy94.gitee.io/" title target='_blank' -->
        <a style="display: block;" href="https://xy94.gitee.io/" title target='_blank'
        >Gitee Pages</a>
      
    </div>
  </div>

  
 
  
</aside>
      </div>
      <footer id="footer">
  <div class="foot-box global-width center">
    &copy; 2023 许嵩老公 &nbsp;&nbsp;
    Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    &nbsp;|&nbsp;主题 <a href="https://github.com/yiluyanxia/hexo-theme-antiquity" target="_blank" rel="noopener">antiquity</a>
    <br>
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">不蒜子告之   阁下是第<span id="busuanzi_value_site_pv"></span>个访客</span>
    
  </div>
  
  <!--引入文字点击特效-->
  <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
  
<script src="../../../../js/dianji.js"></script>

</footer>

<!--添加回到顶部按钮-->
<style>
/* 小猫置顶 */
/* 自定义回到顶部样式 */
.cd-top {
  position: fixed;
  right: 25px;
  top: -900px;
  z-index: 99;
  width: 70px;
  height: 900px;
  /* background: url(https://cdn.jsdelivr.net/gh/moezx/cdn@3.1.9/img/Sakura/images/scroll.png) no-repeat center; */
  background: url(/images/scroll.png) no-repeat center;
  background-size: contain;
  -webkit-transition: all .5s ease-in-out;
  transition: all .5s ease-in-out;
  /* cursor: url(https://cdn.jsdelivr.net/gh/moezx/cdn@3.1.9/img/Sakura/cursor/No_Disponible.cur), auto; */
  cursor: url(/images/cursor/No_Disponible.cur), auto;
  opacity: 1
}

.cd-top.cd-is-visible {
  opacity: 1;
  top: -326px
}

.cd-top.cd-fade-out {
  opacity: 1
}

.cd-top:hover {
  opacity: 1
}

.cd-top span {
  display: none;
  color: #000;
  position: absolute;
  bottom: 0;
  height: 20px;
  width: 50px;
  text-align: center
}

@media screen and (max-width:860px) {
  .cd-top {
      display: none;
      height: 60px;
      width: 50px
  }
  .cd-top span {
      height: 10px;
      width: 50px
  }
}

#moblieGoTop {
  display: none;
  position: fixed;
  bottom: 10px;
  right: 10px;
  z-index: 99;
  border: 0;
  outline: 0;
  background-color: #fff;
  color: #404040;
  cursor: pointer;
  padding: 15px;
  border-radius: 10px;
  border-radius: 12px;
  box-shadow: 0 0 2px 0 rgba(0, 0, 0, .12), 0 2px 2px 0 rgba(0, 0, 0, .24);
  transition: box-shadow .2s ease
}
#moblieGoTop:hover {
  background-color: #fff;
  opacity: .8
}
.changeSkin-gear {
  position: fixed;
  bottom: 0;
  left: auto;
  right: 5px;
  width: auto;
  height: auto;
  z-index: 99;
  white-space: nowrap;
  padding: 10px 10px;
  cursor: pointer;
  border-radius: 10px 10px 0 0
}
</style>

<!-- 添加小猫置顶 -->
<a class="cd-top faa-float animated cd-is-visible cd-fade-out" style="top: -500px;"></a>
<button id="moblieGoTop" title="Go to top" style="display: none;font-size: xx-large;"><i class="fa fa-chevron-up" aria-hidden="true"></i>🔝</button>

<!-- <div class="scroll "> <i class="fa fa-arrow-up" style="margin-left: 4px;"></i>
Top⬆️
<span class="scrollpercent" style="margin-left: -2px;"></span>
<span style="margin-right: 4px; margin-left: -4px;">%</span>
</div> -->

<!-- https://www.huangpinke.com/2018/08/24/add-back-to-top-button.html -->
      <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
if (!window.jQuery) {
var script = document.createElement('script');
script.src = "/js/jquery-2.0.3.min.js";
document.body.write(script);
}
</script>

  
<link rel="stylesheet" href="../../../../fancybox/jquery.fancybox.css">

  
<script src="../../../../fancybox/jquery.fancybox.pack.js"></script>




<script src="../../../../js/script.js"></script>




<script>
  (function(){
      var bp = document.createElement('script');
      bp.src = '//push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
  })();
  </script>

<!-- mermaid图 -->

  <script src='https://unpkg.com/mermaid@7.1.2/dist/mermaid.min.js'></script>
  <script>
    if (window.mermaid) {
      mermaid.initialize({theme: 'forest'});
    }
  </script>

    </div>
    <nav id="mobile-nav" class="mobile-nav-box">
  <div class="mobile-nav-img mobile-nav-top"></div>
  
    <a href="../../../../index.html" class="mobile-nav-link">首页</a>
  
    <a href="../../../../archives" class="mobile-nav-link">归档</a>
  
    <a href="../../../../quick-notes" class="mobile-nav-link">小抄</a>
  
    <a href="../../../../about" class="mobile-nav-link">关于</a>
  
  <div class="mobile-nav-img  mobile-nav-bottom"></div>
</nav>    
  </div>
</body>

</html>